#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <cstdlib>
#include <cstring>
#include <cerrno>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include "err.hpp"
#include "Sock.hpp"
#include "Thread.hpp"
#include "Protocol.hpp"
#include "Daemon.hpp"

namespace ns_server
{
    // 前置声明
    class TcpServer;

    // 线程所需要的基本信息
    struct ThreadData
    {
        ThreadData(const int &sock, const string &ip, const uint16_t &port, TcpServer *pt)
            : _sock(sock), _ip(ip), _port(port), _pt(pt)
        {
            logMessage(Info, "========================================");

            logMessage(Debug, "ThreadData ready %d-%s-%d-%p", _sock, _ip.c_str(), _port, _pt);
        }

        ~ThreadData()
        {
        }

        int _sock;
        std::string _ip;
        uint16_t _port;
        TcpServer *_pt; // 指向TCP对象的指针
    };

    using func_t = function<ns_protocol::Response(const ns_protocol::Request &)>;

    static const uint16_t default_port = 8888; // 默认端口号
    class TcpServer
    {
    public:
        TcpServer(const func_t &func, const uint16_t &port = default_port)
            : _func(func), _port(port)
        {
        }

        ~TcpServer()
        {
            _listen_sock.Close(); // 关闭套接字

            // 关闭线程
            for (auto e : _vt)
                delete e;
        }

        // 初始化服务器
        void InitServer()
        {
            // 创建、绑定、监听
            _listen_sock.Socket();
            _listen_sock.Bind(_port);
            _listen_sock.Listen();

            // Daemon();   //守护进程化
            logMessage(Debug, "Socket Bind Listen Success! %s", strerror(errno));
            logMessage(Debug, "Process Success!", strerror(errno));
        }

        // 启动服务器
        void StartServer()
        {
            int n = 0; // 线程编号
            while (true)
            {
                // 尝试接受客户端的连接请求
                std::string clientip;
                uint16_t clientport;

                int sock = _listen_sock.Accept(&clientip, &clientport);
                if (sock == -1)
                    continue; // 没连上就没必要执行后续动作了

                logMessage(Debug, "Server Link Success! %s %d", clientip.c_str(), clientport);

                // 创建子线程，让其执行任务
                ThreadData *ptd = new ThreadData(sock, clientip, clientport, this);
                Thread *t = new Thread(n++, threadRoutine, ptd);
                _vt.push_back(t);   //回收线程
            }
        }

        // 线程执行函数
        static void *threadRoutine(void *args)
        {
            ThreadData *ptd = static_cast<ThreadData *>(args);

            // 调用真正的业务处理函数
            ptd->_pt->ServiceIO(ptd->_sock, ptd->_ip, ptd->_port);

            delete ptd; // 销毁线程信息
            ptd = nullptr;
            logMessage(Debug, "thread run done: %s", strerror(errno));
        }

        // 业务处理
        void ServiceIO(int sock, const std::string &ip, const uint16_t &port)
        {
            std::string inbuff; // 缓冲区，多次读取时，数据不丢失
            while (true)
            {
                // 1、读取到数据（字符串）
                std::string package; // 读取的包
                int n = ns_protocol::ReadPackage(sock, inbuff, &package);
                std::cout << "server sock: " << sock << endl;
                if (n == ns_protocol::READ_ERR)
                    break;
                else if (n == ns_protocol::READ_KEEP)
                    continue;
                else
                {
                    // 2、去除报头
                    package = ns_protocol::RemoveHeader(package, n);

                    // 3、将数据反序列化
                    ns_protocol::Request req;
                    req.Deserialize(package);
                    
                    //4、业务处理
                    ns_protocol::Response res;
                    res = _func(req);

                    //5、将结果序列化
                    std::string ret;
                    res.Serialize(&ret);

                    //6、添加报头
                    ret = ns_protocol::AddHeader(ret);

                    //7、发送结果
                    send(sock, ret.c_str(), ret.size(), 0);
                }
            }
        }

    private:
        Yohifo::Sock _listen_sock; // 监听套接字
        // std::string _ip;    //服务端不必注明IP
        std::uint16_t _port;
        func_t _func; // 由服务端传入，将 请求 转为 回复 的业务函数
        std::vector<Thread *> _vt;
    };
}
